{"id":349,"date":"2024-02-24T22:19:00","date_gmt":"2024-02-24T22:19:00","guid":{"rendered":"https:\/\/ghothi.co.uk\/?p=349"},"modified":"2025-05-28T08:47:47","modified_gmt":"2025-05-28T08:47:47","slug":"automating-my-daily-construction-news-summary","status":"publish","type":"post","link":"https:\/\/ghothi.co.uk\/?p=349","title":{"rendered":"Automating Construction News"},"content":{"rendered":"\n<p>Reading industry news is part of the job. But doing it manually every day\u2014clicking headlines, skimming paragraphs, filtering out noise\u2014is a time sink.<\/p>\n\n\n\n<p>So I automated it.<\/p>\n\n\n\n<p>The script checks&nbsp;sites like ICE, New Civil Engineer, Construction Enquirer etc., pulls the latest articles, summarises them with GPT, and compiles it all into a single clean HTML file. I open one page, skim the key points, and move on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Workflow<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>Fetch homepage HTML<\/code><\/li>\n\n\n\n<li><code>Extract article links<\/code><\/li>\n\n\n\n<li><code>Filter by publish date<\/code><\/li>\n\n\n\n<li><code>Scrape &amp; clean article body<\/code><\/li>\n\n\n\n<li><code>Convert to markdown<\/code><\/li>\n\n\n\n<li><code>Summarise with GPT<\/code><\/li>\n\n\n\n<li><code>Build HTML report<\/code><\/li>\n<\/ol>\n\n\n\n<p>Summaries look like this:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Title\n\n## Summary\n\n\u2022 Key facts in 4\u20135 bullets\n\n## Lessons (Optional - only included if there's a clear takeaway for consultants or engineers)\n\n\u2022 Key lessons in 2 bullets\n\nLink: [URL link to read more]\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\"># Title<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">## Summary<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\u2022 Key facts in 4\u20135 bullets<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">## Lessons (Optional - only included if there&#39;s a clear takeaway for consultants or engineers)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">\u2022 Key lessons in 2 bullets<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">Link: [URL link to read more]<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Why GPT?<\/h2>\n\n\n\n<p>Most news summarisation tools just truncate the article or paraphrase the intro. Most capable LLMs actually understands both the content and context. Because of this, it can be really good at pulling useful insights for technical topics like engineering, infrastructure, regulation, etc provided it&#8217;s pulling it from a reference source provided in the prompt, and not just from its own latent space.<\/p>\n\n\n\n<p>I&#8217;ve purposely written my prompt to ignore fluff and only output clear, concrete points. It also skips the \u201cLessons\u201d section if there\u2019s nothing meaningful to extract.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Under the Hood<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Article extraction and cleaning<\/h3>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"def _extract_title(soup):\n    h1 = soup.find(&quot;h1&quot;, class_=&quot;name entry-title&quot;)\n    if h1:\n        return h1.get_text(strip=True)\n    return soup.find(&quot;title&quot;).get_text(strip=True)\n\ndef _clean_article(article):\n    for img in article.find_all(&quot;img&quot;): img.decompose()\n    for a in article.find_all(&quot;a&quot;): a.replace_with(a.get_text())\n    return str(article)\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">def<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">_extract_title<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">soup<\/span><span style=\"color: #ECEFF4\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    h1 <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> soup<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">find<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">h1<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">class_<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">name entry-title<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> h1<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> h1<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">get_text<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">strip<\/span><span style=\"color: #81A1C1\">=True<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> soup<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">find<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">title<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">).<\/span><span style=\"color: #88C0D0\">get_text<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">strip<\/span><span style=\"color: #81A1C1\">=True<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">def<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">_clean_article<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">article<\/span><span style=\"color: #ECEFF4\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">for<\/span><span style=\"color: #D8DEE9FF\"> img <\/span><span style=\"color: #81A1C1\">in<\/span><span style=\"color: #D8DEE9FF\"> article<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">find_all<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">img<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">):<\/span><span style=\"color: #D8DEE9FF\"> img<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">decompose<\/span><span style=\"color: #ECEFF4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">for<\/span><span style=\"color: #D8DEE9FF\"> a <\/span><span style=\"color: #81A1C1\">in<\/span><span style=\"color: #D8DEE9FF\"> article<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">find_all<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">a<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">):<\/span><span style=\"color: #D8DEE9FF\"> a<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">replace_with<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">a<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">get_text<\/span><span style=\"color: #ECEFF4\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">str<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">article<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Strips out irrelevant clutter, like ads, links, images, and just leaves the readable content.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Article summarisation<\/h3>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"_PROMPT_TEMPLATE = &quot;&quot;&quot;Summarise the article below into 4-5 bullet points. Each bullet should be specific and include only the most important information, without verbosity or fluff.\n\nAfter the summary, add 1\u20132 bullet points with practical learning points relevant to a civil engineer working on the pre-construction stage of major infrastructure projects. Only include learning points if there is something concrete to learn.\n\nFormat your response as:\n## Summary\n[4-5 bullets]\n## Lessons &lt;only if applicable&gt;\n[1-2 bullets]\n\n&lt;ARTICLE&gt;\n&lt;&lt;ARTICLE_PLACEHOLDER&gt;&gt;\n&lt;\/ARTICLE&gt;\n&quot;&quot;&quot;\n\ndef _summarise(article_md):\n    prompt = _PROMPT_TEMPLATE.replace(&quot;&lt;&lt;ARTICLE&gt;&gt;&quot;, article_md)\n    return client.ChatCompletion.create(\n                model=&quot;gpt-3.5-turbo&quot;,\n                messages=[\n                    {&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: system_role},\n                    {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: my_prompt},\n                ],\n                temperature=temp,\n            )\n    ).[&quot;choices&quot;][0][&quot;message&quot;][&quot;content&quot;]\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\">_PROMPT_TEMPLATE <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;&quot;&quot;<\/span><span style=\"color: #A3BE8C\">Summarise the article below into 4-5 bullet points. Each bullet should be specific and include only the most important information, without verbosity or fluff.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">After the summary, add 1\u20132 bullet points with practical learning points relevant to a civil engineer working on the pre-construction stage of major infrastructure projects. Only include learning points if there is something concrete to learn.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">Format your response as:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">## Summary<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">[4-5 bullets]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">## Lessons &lt;only if applicable&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">[1-2 bullets]<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">&lt;ARTICLE&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">&lt;&lt;ARTICLE_PLACEHOLDER&gt;&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">&lt;\/ARTICLE&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">&quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">def<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">_summarise<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">article_md<\/span><span style=\"color: #ECEFF4\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    prompt <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> _PROMPT_TEMPLATE<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">replace<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">&lt;&lt;ARTICLE&gt;&gt;<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> article_md<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> client<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9FF\">ChatCompletion<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">create<\/span><span style=\"color: #ECEFF4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #D8DEE9\">model<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">gpt-3.5-turbo<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #D8DEE9\">messages<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">[<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                    <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">role<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">system<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">content<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> system_role<\/span><span style=\"color: #ECEFF4\">},<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                    <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">role<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">user<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">content<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> my_prompt<\/span><span style=\"color: #ECEFF4\">},<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #ECEFF4\">],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">                <\/span><span style=\"color: #D8DEE9\">temperature<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\">temp<\/span><span style=\"color: #ECEFF4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    )<\/span><span style=\"color: #ECEFF4\">.[<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">choices<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">][<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">][<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">message<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">][<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">content<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">]<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Report generation<\/h3>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"html = f&quot;&quot;&quot;&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;en&quot;&gt;\n&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;\/&gt;&lt;title&gt;{page_title}&lt;\/title&gt;\n&lt;style&gt;{_PAGE_CSS}&lt;\/style&gt;&lt;\/head&gt;\n&lt;body&gt;&lt;h1&gt;{page_title}&lt;\/h1&gt;{body}\n&lt;footer&gt;Report generated on {timestamp}.&lt;\/footer&gt;&lt;\/body&gt;&lt;\/html&gt;&quot;&quot;&quot;\n\nout_file.write_text(html, encoding=&quot;utf-8&quot;)\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\">html <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">f<\/span><span style=\"color: #A3BE8C\">&quot;&quot;&quot;&lt;!DOCTYPE html&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">&lt;html lang=&quot;en&quot;&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;\/&gt;&lt;title&gt;<\/span><span style=\"color: #EBCB8B\">{<\/span><span style=\"color: #D8DEE9FF\">page_title<\/span><span style=\"color: #EBCB8B\">}<\/span><span style=\"color: #A3BE8C\">&lt;\/title&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">&lt;style&gt;<\/span><span style=\"color: #EBCB8B\">{<\/span><span style=\"color: #D8DEE9FF\">_PAGE_CSS<\/span><span style=\"color: #EBCB8B\">}<\/span><span style=\"color: #A3BE8C\">&lt;\/style&gt;&lt;\/head&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">&lt;body&gt;&lt;h1&gt;<\/span><span style=\"color: #EBCB8B\">{<\/span><span style=\"color: #D8DEE9FF\">page_title<\/span><span style=\"color: #EBCB8B\">}<\/span><span style=\"color: #A3BE8C\">&lt;\/h1&gt;<\/span><span style=\"color: #EBCB8B\">{<\/span><span style=\"color: #D8DEE9FF\">body<\/span><span style=\"color: #EBCB8B\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">&lt;footer&gt;Report generated on <\/span><span style=\"color: #EBCB8B\">{<\/span><span style=\"color: #D8DEE9FF\">timestamp<\/span><span style=\"color: #EBCB8B\">}<\/span><span style=\"color: #A3BE8C\">.&lt;\/footer&gt;&lt;\/body&gt;&lt;\/html&gt;&quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">out_file<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">write_text<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9FF\">html<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">encoding<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">utf-8<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>No dependencies beyond a few standard Python libraries and the OpenAI client. Runs in ~20 seconds, and the output is saved to a HTML file that I can easily open in my browser.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Output Example<\/h2>\n\n\n\n<p>Here&#8217;s an example output produced from the script with absolutely zero editing from me:<\/p>\n\n\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\"\/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\/>\n  <title>NCE Report \u2014 22 February 2024<\/title>\n  <style>\n    \/* make padding & border count inside the width *\/\n    *, *::before, *::after { box-sizing: border-box; }\n\n    body {\n      margin: 0;\n      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n      line-height: 1.6;\n    }\n\n    \/* the new wrapper *\/\n    .report-box {\n      max-width: 780px;\n      margin: 1.5rem auto;\n      border: 1px solid #ffffff; \/* 1px black *\/\n      padding: 15px;          \/* 15px inside *\/\n    }\n\n    \/* your original styles below\u2026 *\/\n    .report-box article { margin-bottom: 4rem; }\n\n    .report-box article h2 {\n      color: #ffffff;\n      margin-top: 0;\n    }\n\n    .report-box article ul {\n      margin-top: .4rem;\n    }\n\n    .report-box section.lessons h3 {\n      color: #ffffff;\n      margin-bottom: .25rem;\n    }\n\n    .report-box a.read-more {\n      display: inline-block;\n      margin-top: .5rem;\n      color: #ffffff;\n      text-decoration: none;\n      font-weight: 500;\n    }\n\n    .report-box a.read-more:hover,\n    .report-box a.read-more:focus {\n      text-decoration: underline;\n    }\n\n    .report-box hr {\n      border: none;\n      border-top: 1px solid #ffffff;\n      margin: 2rem 0;\n    }\n\n    .report-box footer {\n      text-align: center;\n      font-size: .875rem;\n      color: #ffffff;\n      margin-top: 3rem;\n    }\n  <\/style>\n<\/head>\n<body>\n\n  <div class=\"report-box\">\n  <h1>NCE Report \u2014 22 February 2024<\/h1>\n\n  <article>\n    <h2>Silvertown Tunnel opening advanced to early 2025 as cut and cover and road realignment progress<\/h2>\n    <h2>Summary<\/h2>\n    <p>\n      \u2022 The Silvertown Tunnel opening date has been advanced to early 2025 (Q4 2024\/25), previously planned for mid-2025\/26, due to programme mitigations.<br\/>\n      \u2022 The project budget has increased by \u00a32.7M to \u00a3176M to cover bus infrastructure, with a current estimated final cost of \u00a3180M due to inflation and land purchase costs.<br\/>\n      \u2022 Significant progress at the Greenwich site includes completed steel framework of the southern portal, dome installation over the cut-and-cover section, and ongoing reinforced concrete works.<br\/>\n      \u2022 At the Silvertown site, steel framework completion, cladding, dome installation, concrete pours, and waterproofing of the tunnelling have been finished, with utilities and highway works underway.<br\/>\n      \u2022 Several planned Blackwall Tunnel weekend closures will enable road realignment, drainage, gantry installation, and resurfacing to support the new tunnel configuration.\n    <\/p>\n    <h2>Lessons<\/h2>\n    <p>\n      \u2022 Innovative construction techniques (e.g., nitrogen skate for TBM rotation, ground freezing for excavation) can accelerate progress on complex underground infrastructure projects.<br\/>\n      \u2022 Effective coordination of temporary traffic management\u2014including planned closures and temporary bridges\u2014is crucial for maintaining traffic flow while enabling major construction activities.\n    <\/p>\n    <p>\n      <a class=\"read-more\" href=\"https:\/\/www.newcivilengineer.com\/latest\/silvertown-tunnel-opening-advanced-to-early-2025-as-cut-and-cover-and-road-realignment-progress-22-02-2024\/\" target=\"_blank\">\n        Read full article \u2192\n      <\/a>\n    <\/p>\n  <\/article>\n  <hr\/>\n\n  <article>\n    <h2>Legal challenge against trio of A47 upgrades dismissed but may go to Supreme Court<\/h2>\n    <h2>Summary<\/h2>\n    <p>\n      \u2022 Legal challenge against three A47 road upgrade schemes in Norfolk was dismissed by the Court of Appeal, with the Development Consent Orders (DCOs) upheld.<br\/>\n      \u2022 Claimant Andrew Boswell argued the Department for Transport and National Highways failed to properly assess the cumulative climate impact of the road projects.<br\/>\n      \u2022 Court ruled cumulative carbon emissions were adequately assessed within current scientific understanding and legal carbon budgets.<br\/>\n      \u2022 Boswell is considering appealing to the Supreme Court, citing concerns over emissions from four major nearby road projects including the Norwich Western Link.<br\/>\n      \u2022 Norfolk County Council and National Highways welcomed the ruling, highlighting the projects\u2019 importance for reducing congestion, improving safety, and supporting regional growth.\n    <\/p>\n    <h2>Lessons<\/h2>\n    <p>\n      \u2022 Infrastructure projects must carefully document and justify environmental impact assessments, especially cumulative climate impacts, to withstand legal scrutiny.<br\/>\n      \u2022 Clear communication of assessment methodologies and adherence to statutory carbon budgets can strengthen approval defenses in infrastructure disputes.\n    <\/p>\n    <p>\n      <a class=\"read-more\" href=\"https:\/\/www.newcivilengineer.com\/latest\/legal-challenge-against-trio-of-a47-upgrades-dismissed-but-may-go-to-supreme-court-22-02-2024\/\" target=\"_blank\">\n        Read full article \u2192\n      <\/a>\n    <\/p>\n  <\/article>\n  <hr\/>\n\n  <article>\n    <h2>Great British Railways will increase data sharing for better digital twins, industry figures say<\/h2>\n    <h2>Summary<\/h2>\n    <p>\n      \u2022 Great British Railways (GBR) aims to unify UK rail management and enhance data sharing across the sector to improve digital twin technology usage.<br\/>\n      \u2022 Digital twins are seen as models representing real-world infrastructure, used for analysis, experimentation, and decision-making, though standards and definitions remain unclear.<br\/>\n      \u2022 Collaboration between different organizations and sectors (e.g., meteorological services and track monitoring) is key to creating richer, more effective digital twins.<br\/>\n      \u2022 Network Rail is trialing a model combining granular weather forecasts with risk predictions for earthworks failures to optimize train speeds on affected lines.<br\/>\n      \u2022 The Rail Reform Bill supports GBR\u2019s goal of breaking down data-sharing barriers to enable more joined-up decision-making and better infrastructure resilience.\n    <\/p>\n    <h2>Lessons<\/h2>\n    <p>\n      \u2022 Effective digital twin implementation on major infrastructure projects requires cross-sector collaboration and open data sharing to bridge gaps in legacy asset information.<br\/>\n      \u2022 Establishing clear collaboration frameworks and government facilitation can help unify fragmented data sources, driving better risk management and operational efficiency.\n    <\/p>\n    <p>\n      <a class=\"read-more\" href=\"https:\/\/www.newcivilengineer.com\/latest\/great-british-railways-will-increase-data-sharing-for-better-digital-twins-industry-figures-say-22-02-2024\/\" target=\"_blank\">\n        Read full article \u2192\n      <\/a>\n    <\/p>\n  <\/article>\n  <hr\/>\n\n  <article>\n    <h2>Sizewell C early works to commence with site creation and ground trials<\/h2>\n    <h2>Summary<\/h2>\n    <p>\n      \u2022 Sizewell C project has triggered its development consent order, enabling early works including site creation, infrastructure improvements (bypass, A12, park and rides), and ground trials to start.<br\/>\n      \u2022 Early construction involves site roads, perimeter fencing, welfare units, ecological and archaeological works, and drainage and earthworks on soft marshy ground.<br\/>\n      \u2022 A 2km long, 50m deep reinforced concrete cut-off diaphragm wall will form a watertight earth-retaining barrier around the nuclear site before excavating about 4 million cubic meters of material without blasting.<br\/>\n      \u2022 The project is funded by EDF and the UK government, which owns 50% and recently committed an additional \u00a31.3bn to support early construction ahead of a final investment decision.<br\/>\n      \u2022 Sizewell C aims to deliver 3.2GW capacity powering 6 million households, supporting the UK\u2019s goal to quadruple nuclear generation by 2050; tunneling works are decoupled from main excavation, unlike Hinkley Point C.\n    <\/p>\n    <h2>Lessons<\/h2>\n    <p>\n      \u2022 Leveraging lessons and extensive ground investigations from previous projects (Hinkley Point C) is crucial for developing cost-effective construction techniques in challenging geology.<br\/>\n      \u2022 Separating tunneling works from main excavation activities can offer improved management and risk control in complex infrastructure projects.\n    <\/p>\n    <p>\n      <a class=\"read-more\" href=\"https:\/\/www.newcivilengineer.com\/latest\/sizewell-c-early-works-to-commence-with-site-creation-and-ground-trials-22-02-2024\/\" target=\"_blank\">\n        Read full article \u2192\n      <\/a>\n    <\/p>\n  <\/article>\n\n  <footer>\n    Report generated on 22 February 2024, 22:52.\n  <\/footer>\n<\/div>\n\n<\/body>\n<\/html>\n\n\n\n<p><\/p>\n\n\n\n<p>It doesn&#8217;t really replace reading the full articles, but it definitely keeps me up to date and quickly tells me which article I might be interested in.<\/p>\n\n\n\n<p>The next step would be to schedule it via a cron job so it automatically emails me this each morning&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Reading industry news is part of the job. But doing it manually every day\u2014clicking headlines, skimming paragraphs, filtering out noise\u2014is a time sink. So I automated it. The script checks&nbsp;sites like ICE, New Civil Engineer, Construction Enquirer etc., pulls the latest articles, summarises them with GPT, and compiles it all into a single clean HTML [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":353,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,5],"tags":[],"class_list":["post-349","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-ml-automation","category-civil-engineering"],"_links":{"self":[{"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/349","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=349"}],"version-history":[{"count":4,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/349\/revisions"}],"predecessor-version":[{"id":356,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/349\/revisions\/356"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=\/wp\/v2\/media\/353"}],"wp:attachment":[{"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=349"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=349"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ghothi.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=349"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}