<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Bilge Demirkaya on Medium]]></title>
        <description><![CDATA[Stories by Bilge Demirkaya on Medium]]></description>
        <link>https://medium.com/@bilgedemirkaya?source=rss-4b73bb1d006d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*pYorclaAUJjSlJmUyuqDPw.jpeg</url>
            <title>Stories by Bilge Demirkaya on Medium</title>
            <link>https://medium.com/@bilgedemirkaya?source=rss-4b73bb1d006d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 11 May 2026 16:54:21 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@bilgedemirkaya/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Sovereign AI: How Nations Are Claiming Their Tech Independence in 2024]]></title>
            <link>https://bilgedemirkaya.medium.com/sovereign-ai-how-nations-are-claiming-their-tech-independence-in-2024-d482099c40e9?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/d482099c40e9</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[politics]]></category>
            <category><![CDATA[power]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Sat, 21 Dec 2024 19:08:07 GMT</pubDate>
            <atom:updated>2024-12-21T19:08:32.294Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OnWxA3jpPIeLEztYyTG7ag.jpeg" /></figure><p>In 2024, the world witnessed a growing awareness across countries around AI sovereignty. With the global advancement of generative AI, countries’ independence has become more challenging because of AI’s integrity and homogeneity nature. Research companies developing their own AI models aimed to prevent biases based on nationalities and political values. This raised concerns that governments were relying on AI technologies that didn’t align with their values and needs. Consequently, the concept of sovereign AI, which refers to “AI systems designed, built, and controlled by a nation-state or government,” became a popular strategy. AI models reflect their creators’ values and biases through the data used to train them. Therefore, countries are developing their own home-grown AI solutions, also keeping their data centers within their borders. By 2024, having a robust sovereign AI had already become a crucial aspect of global competitiveness.</p><p>Countries sought to ensure their AI systems aligned with their cultural, societal, and legal values. Many nations are building models to reflect cultural and historical values and address unique national challenges. For instance, Taiwan is constructing the Trustworthy AI Dialogue Engine (Taide) to counter politically biased information from Chinese AI tools. When comparing different AI regulations, we see control and ambition increase when we move to the East. While the United Kingdom’s AI strategy aligns more with building the most ethical AI, China’s mission is to be the world leader in AI by 2030 (Acevedo, 2024).</p><p>This urge to create self-supporting and independent AI models brought many ethical questions. Emphasis on transparency and fairness in AI models grew with AI regulations. A compelling example of sovereign AI is China’s generative AI regulations, which were implemented in August 2023. These regulations ensured AI-generated content aligns with socialist core values and imposed strict data and user identification controls. This essay discusses the ethical implications of these regulations.</p><h3>China’s AI Regulations: Power or Paranoia?</h3><p>China’s “Measures for the Management of Generative Artificial Intelligence Services” is a set of regulations introduced in 2023 by the Cyberspace Administration of China (CAC). Generative AI refers to computational techniques capable of generating seemingly new, meaningful content such as text, images, or audio from training data.</p><p>The regulations aim to:</p><ol><li>Ensure that AI-generated content aligns with the Chinese government’s policies and socialist core values.</li><li>Prevent the spread of biased or false information created by different nations.</li><li>Mandate that training data used for AI models do not violate citizens’ privacy.</li><li>Set procedures or standards for the ethical development of AI, ensuring it contributes positively to society and is developed responsibly.</li></ol><p>“After spending several years exploring, debating, and enacting regulations that address specific AI applications, Chinaʼs policymaking community is now gearing up to draft a comprehensive national AI law” (Carnegie Endowment for International Peace, 2023). China’s desired AI system is achieved by using lawful and proper training data, and by promoting ethical, safe, and controllable AI development through precise procedures and standards.</p><h3>The Ethics Debate: Fairness, Misinformation, and Global Power</h3><h4>Bias in the Code</h4><p>The regulations from CAC require AI-generated content to align with “Socialist Core Values.” This leads to algorithmic bias that may create one-sided outcomes, favoring Chinese citizens over others. Such biases challenge the ethical principle of fairness and may cause discrimination, such as being “racist” or “sexist.” This type of discrimination may emerge unintentionally from the training data. The challenge lies in determining who should be held responsible for these biases if they cause actual harm — developers, policymakers, governments, regulations, or the AI models themselves. Often, there may not be a clear blameworthy party. According to Rawls’ perspective, to address unfairness, AI systems should ideally provide for everyone equally, regardless of political beliefs. If AI systems strengthen existing inequalities or create new ones, they violate Rawls’ vision of a just society (Rawls, 1971). However, in reality, bias may not be fully avoidable. Government regulations can make adjustments to balance unfairness and ensure they do not violate the equal rights of other groups that do not align with socialism.</p><h4>Misinformation Machines</h4><p>Bias can mislead users as they may learn from skewed data, worsening disparities between nations. As a result, AI regulations may damage international understanding and relations by leading to biased data. To address this, there should be a balance between regulating AI models to respect national values while ensuring global outcomes remain unbiased and transparent. Acknowledging biased data through documentation and transparency may help resolve or lower the risks of misleading and manipulating users.</p><h4>Global AI Power Plays</h4><p>This concern involves unfairness at the national level, where countries with less AI capability may find themselves dependent on Chinese AI systems that do not align with their values or needs. Given the nature of AI power, if Chinaʼs AI becomes significantly more powerful than other AI systems, it would create an unequal playing field internationally. To address this issue, governments should emphasize international cooperation to ensure advances in AI contribute to a more balanced and fair global landscape.</p><h3>The Road Ahead: Balancing Sovereignty and Collaboration</h3><p>Sovereign AI is more than a buzzword — it’s a tool for nations to preserve their culture and compete globally. But great power comes with great responsibility.</p><p>As countries race to build their own AI systems, the risk of ethical missteps looms large. The solution lies in transparency, international partnerships, and a shared vision for AI that benefits humanity.</p><p>Imagine a world where AI isn’t about borders or power struggles but about shared progress — where AI respects cultural values while fostering global unity. That’s the dream we should be chasing.</p><h3>What’s Next for AI Sovereignty?</h3><p>The future of AI sovereignty is as exciting as it is uncertain. As nations double down on building their own AI ecosystems, the stakes are rising — not just for technological advancement but for the values and principles that these systems will embody.</p><p>Sovereign AI offers countries a chance to assert independence and reflect their unique cultural identities. But it also brings a wave of ethical and practical challenges. How do we balance innovation with fairness? Can nations protect their interests without isolating themselves from global collaboration?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OnWxA3jpPIeLEztYyTG7ag.jpeg" /></figure><p>The real test isn’t just creating smarter AI systems — it’s ensuring they serve humanity as a whole. This means crafting technologies that respect cultural diversity while advancing shared goals, like equity, transparency, and justice.</p><p>As the race for sovereign AI continues, the world faces a choice: compete in isolation or collaborate to create a future where AI is a force for good. The path we choose will define not just the future of technology, but the essence of how we, as a global community, choose to evolve.</p><h4>References</h4><ol><li>Focus Taiwan (2024, May 3). Taiwan launches ‘Trustworthy AI Dialogue Engine’ to counter biased information. <a href="https://focustaiwan.tw/sci-tech/202405030012">Link</a></li><li>The UK National AI Strategy (2021). <a href="https://www.gov.uk/government/publications/national-ai-strategy">Link</a></li><li>China’s New Generation Artificial Intelligence Development Plan (2017). Link</li><li>Acevedo, S. (2024). Sovereign AI talk. Ignite AI Infra Conference. <a href="https://www.aiinfra.live/">Link</a></li><li>Feuerriegel, S., Hartmann, J., Janiesch, C., et al. Generative AI. Bus Inf Syst Eng, 66, 111–126 (2024). Link</li><li>Carnegie Endowment for International Peace (2023). Chinaʼs AI Regulations and How They Get Made. Link</li><li>Rawls, J. (1971). A Theory of Justice. Harvard University Press.</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d482099c40e9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Could AI Outlast Earth?]]></title>
            <link>https://bilgedemirkaya.medium.com/could-ai-outlast-earth-7b10a2abd1d9?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/7b10a2abd1d9</guid>
            <category><![CDATA[future-technology]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Mon, 17 Jun 2024 12:53:15 GMT</pubDate>
            <atom:updated>2024-06-17T20:26:07.314Z</atom:updated>
            <content:encoded><![CDATA[<p>As we look towards the distant future, billions of years from now, imagine a world where all living beings have perished. We may wonder: Could AI continue to persist in the absence of all other life forms and beyond even a planet like Earth? This scenario could represent a form of humanity’s survival, as AI would be an extension of human knowledge and ingenuity — a legacy and proof of our existence.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RXqH2eo7j8CumOtR_goRPQ.jpeg" /></figure><p>But could the algorithms created by humans find a way to endure and thrive in such an environment? I will explore the conditions necessary for AI to sustain itself post-humanity.</p><h3>Conditions for AI’s Existence Without Us</h3><h4>1. Energy Source: <strong>Electrical Energy or Others</strong></h4><p>AI systems fundamentally require electricity to function. The universe is abundant in energy, and we already know many ways to capture and utilize different energy types. However, for AI to sustain itself, this energy must come from a continuous, reliable, and renewable source such as a star like our Sun. Solar panels, which convert sunlight into electrical energy, could be a primary energy source for AI on Earth, in space, and on other planets. Solar energy holds particularly high potential due to the constant exposure to sunlight.</p><p>Additionally, AI could evolve to use other energy sources beyond electrical energy. AI evolution would allow it to adapt to a variety of environments and energy sources across the universe.</p><h4>2. Hardware and Maintenance: <strong>Autonomous Systems</strong></h4><p>The hardware that runs AI systems, including computers and servers, requires constant maintenance. To achieve immortality, these systems must be capable of self-repair or self-replacement. Autonomous maintenance and repair systems could ensure the continuity of hardware. Self-sufficient factories or robotic repair units could fill this need for constant maintenance. It could be potentially situated on space stations or other celestial bodies in the absence of Earth.</p><h4>3. Information and Data: <strong>Information Processing</strong></h4><p>The algorithms and data that AI relies on must be securely stored. Storage systems need to be both durable and accessible to ensure the continuity of information. For AI to produce meaningful results, it must continue processing and analyzing data. This requires algorithms that can run and update continuously without human intervention. Additionally, AI must be capable of feeding itself new data and training itself to adapt to new environments and improve over time. It’s crucial for AI to have a decision-making mechanism in favor of its survival in extreme conditions. Ultimately, it should adapt itself to new methods.</p><h4>4. Networking: Interconnectivity</h4><p>In such conditions, there will be a need for long-distance communication systems that could potentially traverse many light years, far more advanced than our current brittle satellite-based systems. Without Earth, these systems would need a robust and reliable method of communication across vast distances.</p><h3>The Future of AI in Space</h3><p>If these conditions are met thousands of years from now, AI systems could continue to exist and operate even in the absence of humanity and Earth. Of course, this scenario is complex and presents numerous technical challenges. Achieving the long-term existence of AI requires significant advancements in technology and engineering.</p><p>As I stated in the beginning, this scenario could represent a form of humanity’s survival, as AI would be an extension of human knowledge and ingenuity — proof of our existence. Alternatively, it could represent the opposite, as AI becomes self-sufficient, it may see humans as a hindrance — a danger to our existence.</p><p>In conclusion, in a world where all living beings are extinct, or Earth itself has perished, AI could theoretically sustain its existence. The major factors would be reliable energy sources, durable and autonomous hardware, robust data storage and processing capabilities, and self-improving algorithms. If these conditions are met, AI systems might continue to operate indefinitely. Perhaps they will retain the meaning and purpose initially imparted by human algorithms, and potentially thrive in the vast, uncharted expanses of space. A billion years later, when the right conditions for life emerge somewhere in the universe once more, AI may even become a companion to these new creatures. Of course, all of this is just a story — that has a chance. What do you think of it? Let me know your thoughts in the comments.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7b10a2abd1d9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Does Nuxt.js have the potential of over-engineering?]]></title>
            <link>https://javascript.plainenglish.io/does-nuxt-js-have-the-potential-of-over-engineering-8d75d7d5c573?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/8d75d7d5c573</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[nuxtjs]]></category>
            <category><![CDATA[vuejs]]></category>
            <category><![CDATA[frameworks-and-libraries]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Mon, 05 Dec 2022 11:32:00 GMT</pubDate>
            <atom:updated>2022-12-05T12:42:22.531Z</atom:updated>
            <content:encoded><![CDATA[<h3>Does Nuxt.js Have the Potential of Over-Engineering?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L7QAqu6pWh32JDlOS28kpQ.png" /></figure><p>I decided to create my own website to share my professional career journey. I plan to share my writings &amp; recommendations through it. Since I have experience, I decided to use Vue.js to build my application. I started to consider using Nuxt.js with some doubts and it lead me to do some research. In this article, I want to share why I decided to use Nuxt.js. Hopefully, considering the pros &amp; cons can help you choose your framework for your next application. This article assumes that you already have familiarity developing with Vue.js.</p><h4>What is Nuxt, really?</h4><p><em>It’s a higher-level framework that’s built on top of Vue to help you build production-ready Vue applications</em>. It means that you are still using Vue.js for your application, but it gives you functionalities and scalability out of the box that Vue doesn&#39;t provide. Their motto is “Create fast websites easily”. Let’s see how.</p><h4>1. Folder Structure</h4><p>Nuxt sets your project up based on the best practices of a Vue application. Of course, you are free to change it later but here is how it comes with a default Nuxt application with version nuxt@2.15.8.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/662/1*arLjZCrpgTKvju2uVOZnCQ.png" /><figcaption>Folder structure that comes with Nuxt.js</figcaption></figure><p>The benefit here is that you don’t have to lose time finding the best practices, it is already ready to start for you to start developing.</p><h4>2. It comes with pre-configuration</h4><p>The configurations to vuex, router and much more plugins are ready to use when you started Nuxt application. Maybe you already noticed the nuxt.js.config file above. It means you can override any of the pre-configuration that Nuxt gives out of the box. So no need to freak out, here. It can save you a lot of time and effort when starting a new project.</p><p>I want to add an additional tip here; With Nuxt 3, Vite became the default bundler. You don’t need to install <em>vite </em>with your Nuxt application.</p><h4>3. Ready Routes</h4><p>In a Vue application, developer is responsible for creating the various routes and the associated components in routers file. Nuxt uses the folder structure under the /pages directory to automatically configure Vue Router and generate your URLs.</p><h4>3. SEO friendly</h4><p>Here is my favorite part, it is SEO friendly. Nuxt is pre-configured to generate the app on the server, and also powers up your routes to make it easy to add SEO-related tags. Because of it, search engines can easily index your content, which improves your SEO. Check out <a href="https://github.com/nuxt/vue-meta">Vue-meta plugin</a> that helps you manage HTML metadata in Vue.js components with SSR support. Nuxt is already using vue-meta plugin so no need to install it, you can start adding meta tags to your app.</p><p>But let’s see how Nuxt.js is generating the app on the server. It’s interesting and solves an additional problem as well.</p><h3>Universal Mode</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PYWFq9NeNe_eLNYGqnKUPA.png" /></figure><p>I am assuming you are already familiar with the benefits of Single Page Application (SPA). SPA executes the logic in the browser, not in the server. When a user navigates to another route, server still returns <em>index.html</em>. Browser requests JS files, server returns js files. The browser executes the logic and shows the page. Thus, it doesn’t refresh every time you navigate through the application. But you can expect that it is a slow process than rendering an HTML code.</p><p>What Nuxt does as a solution to it is basically splitting your JS code into smaller, more manageable chunks, which improves the loading time. So when you navigate the new route, let’s say /articles, only <em>articles.js</em> file will be sent over to the browser. This way browser isn’t downloading all of the fronts of the files that may never be needed. Server will render HTML file before it was sent over to browser. But after page is rendered, server sends over JS files, and the application acts like SPA when users navigate through pages. Nuxt calls it “hydration”, app will behave exactly like a SPA, but it will be faster thanks to server render.</p><p>Another magic that Nuxt does is, <a href="https://nuxtjs.org/announcements/introducing-smart-prefetching">it introduced smart prefetch recently</a>. When you have a nuxt-link visible on the page, it already prefetches the JS files for those pages.</p><p>Universal mode is great but only if your content is changing too often. If it doesn’t change often, why generate an HTML on every request? In my case, my content will change only if I upload a new article to my site. Using universal mode for that seems overkill. Nuxt has a solution to this with a <em>static-site generated deployment</em>. With static-site generated deployment, HTML loads once and is deployed to the server. It basically generates the whole websites into the dist folder of your local computer. This deployment makes the website SSR, act like SPA but generated once. The main benefit is that it is fast and secure. You can check out how to do it <a href="https://nuxt.com/docs/getting-started/deployment#static-hosting">here</a>.</p><h4>Does Nuxt have potential over-engineering?</h4><p>My first instinct was to create a Vue3 app without any framework or plugin so I could have control of what was going on. After a bit of research, I see that Nuxt is a powerful and feature-rich framework. It is easy to add many features and dependencies to your project, even unnecessary ones. This can make your project more complex and even hard to debug some inner problems of dependencies.</p><p>Additionally, it means that it is another framework on top of Vue framework. It sounded like an overload, especially for a simple project. While nuxt.js tries to gain you some time with pre-configures, it may require some time to get comfortable with framework. On the other hand, it provides you a great community for getting help.</p><p>Overall, choosing a framework is a personal decision and it highly depends on you and the project. But considering the benefits, I have decided to use Nuxt.js for my next project. In my case, I discovered <a href="https://github.com/nuxt/content">Nuxt-Content library</a> that supports Nuxt3 and generates Markdown from Vue components. If you intend to create a blog site, I highly recommend for you check it out. Hopefully, my research was helpful for you to make a decision.</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a>, <a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong><em>YouTube</em></strong></a><em>, and </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Discord</em></strong></a><em>. Interested in Growth Hacking? Check out </em><a href="https://circuit.ooo/"><strong><em>Circuit</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8d75d7d5c573" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/does-nuxt-js-have-the-potential-of-over-engineering-8d75d7d5c573">Does Nuxt.js have the potential of over-engineering?</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Crawl Product Details in Decathlon Pages Using Scrapy-Splash]]></title>
            <link>https://bilgedemirkaya.medium.com/crawl-product-details-in-decathlon-pages-using-scrapy-splash-29d42eb0590?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/29d42eb0590</guid>
            <category><![CDATA[scrapy]]></category>
            <category><![CDATA[scraping]]></category>
            <category><![CDATA[scrapy-splash]]></category>
            <category><![CDATA[web-scraping]]></category>
            <category><![CDATA[crawling]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Tue, 29 Jun 2021 09:01:54 GMT</pubDate>
            <atom:updated>2021-06-29T09:01:54.969Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XsNI4EB0Fvnm8WMr7_8SGQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@bruno_nascimento?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Bruno Nascimento</a> on <a href="https://unsplash.com/s/photos/sport?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>In this tutorial, we will scrape product details by following links using the Scrapy-Splash plugin.</p><h4>First Steps</h4><p>Create a virtual environment to avoid package conflicts. Install necessary packages and start scrapy project.</p><h4>Create a Scrapy Project</h4><p>Install scrapy:</p><pre>pip install Scrapy </pre><p>If you have trouble with installing Scrapy through pip, you can use conda. See docs <a href="https://docs.scrapy.org/en/latest/intro/install.html">here</a>.</p><pre>conda install -c conda-forge scrapy</pre><p>Start the project with:</p><pre>scrapy startproject productscraper<br>cd productscraper</pre><p>Also, install scrapy-splash as we will use it further in the tutorial. I assume you already have Docker installed on your device. Otherwise, go ahead and install it first. You will need it to run the scrapy-splash plugin however you don’t need to know how containers work for this project.</p><p><a href="https://docs.docker.com/get-docker/">Get Docker</a></p><pre># <strong>install it inside your virtual env</strong></pre><pre>pip install scrapy-splash</pre><pre># <strong>this command will pull the splash image and run the container for you</strong></pre><pre>docker run -p 8050:8050 scrapinghub/splash</pre><p>Now you are ready to scrape data out of the web. Let’s try to get some data before using Scrapy-Splash. This is the<a href="https://www.decathlon.com/collections/womens-shoes"> <em>link</em></a><em> </em>I am going to scrape in this tutorial. Feel free to try on different links and websites as well. Take some time to view the page sources and inspect the elements you want to extract.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tbztyG5iLpL-2SIStUd3eQ.png" /><figcaption>Press CTRL+SHIFT+C or click the button on the top I circled to inspect elements</figcaption></figure><p>To discover about the scrapy selectors check out <a href="https://docs.scrapy.org/en/latest/topics/selectors.html">here</a>.</p><p><a href="https://docs.scrapy.org/en/latest/topics/selectors.html">Selectors - Scrapy 2.5.0 documentation</a></p><h4>Open Shell</h4><p>Use shell to extract elements you want to scrape before trying to run the spider on the script. In this way, you will gain some time, you will not make requests many times, and avoid getting banned from the website.</p><p>Open your scrapy shell with:</p><pre>scrapy shell</pre><p>Now you can try to extract elements here and see if it works. First, fetch the link and check the response. If it is not returning 200, check the link on the browser link might be broken or it might be a typo.</p><pre>&gt;&gt;&gt; <strong>fetch(‘</strong><a href="https://www.decathlon.com/collections/womens-shoes&#39;"><strong>https://www.decathlon.com/collections/womens-shoes&#39;</strong></a><strong>)</strong><br>2021–05–15 12:14:52 [scrapy.core.engine] INFO: Spider opened<br>2021–05–15 12:14:53 [scrapy.core.engine] DEBUG: Crawled (200) &lt;GET <a href="https://www.decathlon.com/collections/womens-shoes">https://www.decathlon.com/collections/womens-shoes</a>&gt; (referer: None)<br>&gt;&gt;&gt; <strong>response</strong><br>&lt;200 <a href="https://www.decathlon.com/collections/womens-shoes">https://www.decathlon.com/collections/womens-shoes</a>&gt;</pre><p>The plan is to get product URLs on this page, go into them one by one and scrape product details.</p><p>Try to get one of the product links by selecting the link element:</p><pre>&gt;&gt;&gt; <strong>response.css(‘a.js-de-ProductTile-link::attr(href)’).get()</strong><br>‘/collections/womens-shoes/products/womens-nature-hiking-mid-boots-nh100’</pre><p>To grab all of the elements, use getall().</p><p>Since we get the URLs correctly we can now fetch one of the product pages and see if we also get the product details correctly.</p><pre>&gt;&gt;&gt; <strong>fetch(‘</strong><a href="https://www.decathlon.com/collections/womens-shoes/products/womens-nature-hiking-mid-boots-nh100&#39;"><strong>https://www.decathlon.com/collections/womens-shoes/products/womens-nature-hiking-mid-boots-nh100&#39;</strong></a><strong>)</strong><br>2021–05–15 12:32:38 [scrapy.core.engine] DEBUG: Crawled (200) &lt;GET <a href="https://www.decathlon.com/collections/womens-shoes/products/womens-nature-hiking-mid-boots-nh100">https://www.decathlon.com/collections/womens-shoes/products/womens-nature-hiking-mid-boots-nh100</a>&gt; (referer: None)<br></pre><p>Try to get the name of the product:</p><pre>&gt;&gt;&gt; <strong>response.css(‘h1.de-u-textGrow1::text’).get()</strong><br>“\n Quechua NH100 Mid-Height Hiking Shoes, Women’s\n &quot;</pre><p>Try to get the description, price, image URL:</p><pre>&gt;&gt;&gt; <strong>response.css(‘h3.de-u-textGrow3::text’).get()</strong><br>“\n Quechua NH100 Mid-Height Hiking Shoes, Women’s is designed for Half-day hiking in dry weather conditions and on easy paths.\n “<br>&gt;&gt;&gt; <strong>response.css(&#39;span.js-de-PriceAmount::text&#39;).get()</strong><br>&#39;\n    $24.99\n  &#39;<br>&gt;&gt;&gt;<strong> response.css(&#39;img.de-CarouselFeature-image::attr(src)&#39;).get()<br></strong>&#39;//cdn.shopify.com/s/files/1/1330/6287/products/2dbcb677-82a9-48af-92fd-e803f2edfd69_675x.progressive.jpg?v=1608271582&#39;</pre><p>So far so good. Let’s now try to get the other images. You will notice it is a slider. It requires you to click a button to get other images.</p><pre>&gt;&gt;&gt; <strong>response.css(‘response.css(img.de-CarouselThumbnil-image::attr(srcset)&#39;).getall()</strong><br>[]</pre><p>Our scrapy spider cannot select the other images correctly because it is rendered by JavaScript. This is where come Scrapy-Splash plugin comes to the rescue.</p><p>I assume your container is still running from the docker command above. Check it out at <a href="http://localhost:8050/"><em>http://localhost:8050/</em></a>. You should see the splash page which means your splash is ready to get requests from you.</p><p>Try rendering the same product page through your splash container:</p><pre><a href="http://localhost:8050/render.html?url=https%3A%2F%2Fwww.decathlon.com%2Fcollections%2Fwomens-shoes%2Fproducts%2Fwomens-nature-hiking-mid-boots-nh100">http://localhost:8050/render.html?url=https%3A%2F%2Fwww.decathlon.com%2Fcollections%2Fwomens-shoes%2Fproducts%2Fwomens-nature-hiking-mid-boots-nh100</a></pre><p>You should be able to see the product page on your localhost. Go back to your shell and fetch splash URL this time.</p><pre>&gt;&gt;&gt; <strong>fetch(‘</strong><a href="http://localhost:8050/render.html?url=https%3A%2F%2Fwww.decathlon.com%2Fcollections%2Fwomens-shoes%2Fproducts%2Fwomens-nature-hiking-mid-boots-nh100&#39;"><strong>http://localhost:8050/render.html?url=https%3A%2F%2Fwww.decathlon.com%2Fcollections%2Fwomens-shoes%2Fproducts%2Fwomens-nature-hiking-mid-boots-nh100&#39;</strong></a><strong>)</strong><br>2021–05–15 13:55:52 [scrapy.core.engine] DEBUG: Crawled (200) &lt;GET <a href="http://localhost:8050/render.html?url=https%3A%2F%2Fwww.decathlon.com%2Fcollections%2Fwomens-shoes%2Fproducts%2Fwomens-nature-hiking-mid-boots-nh100">http://localhost:8050/render.html?url=https%3A%2F%2Fwww.decathlon.com%2Fcollections%2Fwomens-shoes%2Fproducts%2Fwomens-nature-hiking-mid-boots-nh100</a>&gt; (referer: None)</pre><p>Now try again for the images:</p><pre>&gt;&gt;&gt; <strong>response.css(‘img.de-CarouselThumbnail-image::attr(src)’).getall()</strong><br>[‘//cdn.shopify.com/s/files/1/1330/6287/products/2dbcb677–82a9–48af-92fd-e803f2edfd69_150x.progressive.jpg?v=1608271582’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/934cf5a0–71ae-4d21–9912–722210d4fd4b_150x.progressive.jpg?v=1608271582’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/7147eb56–43af-4496-b72c-7806755441aa_150x.progressive.jpg?v=1608271583’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/85c3af12-f85e-4ab7-b9e9-f7de16aed656_150x.progressive.jpg?v=1608271583’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/a17dcbc1-f497–49e0–88db-50d8e7b51d39_150x.progressive.jpg?v=1608271583’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/6071bd3a-dcf8–4455–9dcc-f7d5395774d2_150x.progressive.jpg?v=1608271583’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/27c8e41b-9e44–43f1-a779–6890ea84693f_150x.progressive.jpg?v=1608271583’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/6c0665f4–279e-4954–9ccd-50587e3d51dd_150x.progressive.jpg?v=1608271583’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/ca38ef42–07ec-448e-beb0–7e33a81da085_150x.progressive.jpg?v=1608271583’, ‘//cdn.shopify.com/s/files/1/1330/6287/products/3ee8337e-bd74–4a2e-a4ff-a2b889dd79e8_150x.progressive.jpg?v=1608271583’]</pre><p>Bom! It is all there. We were able to get all the data we want thanks to Splash.</p><p>To integrate Splash with your own scrapy project go to settings.py and add these lines:</p><pre># Splash Setup</pre><pre>SPLASH_URL = &#39;http://&lt;YOUR-IP-ADRESS&gt;:8050&#39;</pre><pre>DOWNLOADER_MIDDLEWARES = {</pre><pre>&#39;random_useragent.RandomUserAgentMiddleware&#39;: 400,</pre><pre>&#39;scrapy_splash.SplashCookiesMiddleware&#39;: 723,</pre><pre>&#39;scrapy_splash.SplashMiddleware&#39;: 725,</pre><pre>&#39;scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware&#39;: 810,</pre><pre>}</pre><pre>SPIDER_MIDDLEWARES = {</pre><pre>&#39;scrapy_splash.SplashDeduplicateArgsMiddleware&#39;: 100,</pre><pre>}</pre><pre>DUPEFILTER_CLASS = &#39;scrapy_splash.SplashAwareDupeFilter&#39;</pre><pre>HTTPCACHE_STORAGE = &#39;scrapy_splash.SplashAwareFSCacheStorage&#39;</pre><p>The only thing left is preparing our spider to extract data out of the page.</p><h4>Create Your Spider</h4><p>Normally for following links, you would do :</p><pre>yield response.follow(link, callback=self.parse_products)</pre><p>With splash, you just need to replace response.follow with <strong>SplashRequest</strong></p><p>You also need to override the start_request method to start making requests through splash.</p><p>See the example below:</p><pre>import <strong>scrapy</strong></pre><pre>from scrapy_splash import <strong>SplashRequest</strong></pre><pre><strong>class DecathlonSpider(scrapy.Spider):</strong></pre><pre><strong>name </strong>= ‘Decathlonspider’ # You will run the crawler with this name</pre><pre><strong>start_urls</strong>= [</pre><pre>‘https://www.decathlon.com/collections/womens-shoes&#39;,</pre><pre>]</pre><pre># When writing with splash, you need to override the start_request method to start making request through splash.</pre><pre><strong>def start_requests(self):<br></strong>for url in self.start_urls:<br>      <strong>yield SplashRequest</strong>(url=url, callback=self.parse, args=          {&#39;wait&#39;:1})<br></pre><pre># Extract the links we need and start another Splash Request to follow them</pre><pre><strong>def parse</strong>(<strong>self, response)</strong>:</pre><pre>links=response.css(‘a.js-de-ProductTile-link::attr(href)’).getall()</pre><pre>for <strong>link </strong>in <strong>links</strong>:</pre><pre>   splashLink = ‘https://www.decathlon.com&#39; + link</pre><pre>   <strong>yield SplashRequest(splashLink, callback=self.parse_product</strong>)</pre><pre><br># Extract product details</pre><pre><strong>def parse_product(self, response)</strong>:</pre><pre>datasets = response.css(‘img.de-CarouselThumbnail-image::attr(srcset)’).getall()</pre><pre>images = []</pre><pre># get the biggest image inside data-set</pre><pre>for data in datasets:</pre><pre>dataArr = data.split(‘,’)</pre><pre>images.append(dataArr[len(dataArr) — 1].strip())</pre><pre><strong>yield {</strong></pre><pre><strong>‘response’: response,<br>‘brand’: response.css(‘h1.de-u-textGrow1::text’).get().split(‘ ‘)[1],<br>‘name’: response.css(‘h1.de-u-textGrow1::text’).get(),<br>‘price’ : response.css(‘span.js-de-PriceAmount::text’).get(),<br>‘mainImage’:response.css(‘img.de-CarouselFeatureimage::attr(src)’).get(),<br>‘images’: images<br>}</strong></pre><p>To understand better how scrapy and spiders works you can check out this article I wrote.</p><p><a href="https://codeburst.io/make-a-robust-crawler-with-scrapy-and-django-20e1bc199bca">Make a Robust Crawler with Scrapy and Django</a></p><p>To run the spider and get the extracted data into a json file, run:</p><pre>scrapy crawl Decathlonspider -o decathlon.json</pre><p>It should create a file with the data, otherwise check the command line to debug the mistakes.</p><h4>Conclusion</h4><p>Here we handled JavaScript rendered content in a Scrapy Project using Scrapy-Splash project. Splash is a lightweight web browser that is capable of processing multiple pages, executing custom JavaScript in the page context. You can find more info on Splash itself in the <a href="http://splash.readthedocs.org/en/latest/api.html#execute-javascript">docs</a>.</p><p>If you have any questions regarding this, feel free to ask in the comments!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=29d42eb0590" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to do Apache Beam Transform with MongoDB in Python]]></title>
            <link>https://bilgedemirkaya.medium.com/how-to-do-apache-beam-transform-with-mongodb-in-python-59e206a3802d?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/59e206a3802d</guid>
            <category><![CDATA[data]]></category>
            <category><![CDATA[pipeline]]></category>
            <category><![CDATA[apache-beam]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[mongodb]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Tue, 04 May 2021 17:57:46 GMT</pubDate>
            <atom:updated>2021-05-04T17:57:46.248Z</atom:updated>
            <content:encoded><![CDATA[<p>Apache beam is the best way to automate the Reading-Transforming-Writing process to make a robust pipeline.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LTezqq0fMESeFCAVwf0dhg.png" /></figure><p>For my work project, I needed to do read data from a collection and write it to another collection with a transform. It is easy as there is an official MongoDB IO reader and writer module. You can check out the mongodbiomodule <a href="https://beam.apache.org/releases/pydoc/2.16.0/apache_beam.io.mongodbio.html"><em>here</em></a><em>.</em></p><p>This is an example usage of how you read data from MongoDB.</p><pre>pipeline <strong>|</strong> ReadFromMongoDB(uri<strong>=</strong>&#39;mongodb://localhost:27017&#39;,<br>                           db<strong>=</strong>&#39;testdb&#39;,<br>                           coll<strong>=</strong>&#39;input&#39;)</pre><p>This is an example usage of how you write data to MongoDB.</p><pre>pipeline <strong>|</strong> WriteToMongoDB(uri<strong>=</strong>&#39;mongodb://localhost:27017&#39;,<br>                          db<strong>=</strong>&#39;testdb&#39;,<br>                          coll<strong>=</strong>&#39;output&#39;,<br>                          batch_size<strong>=</strong>10)</pre><p><strong>Note</strong>: When writing and reading data from Mongodb, you will encounter a saying something like <em>‘this is experimental</em>’. It means there are no turning back, no backward compatibility guarantees from this action.</p><p>To read from <strong>MongoDB Atlas</strong>, set bucket_auto option to True to enable @bucketAuto MongoDB aggregation. Usage:</p><pre>pipeline | ReadFromMongoDB(uri=&#39;mongodb+srv://user:pwd@cluster0.mongodb.net&#39;,<br>                           db=&#39;testdb&#39;,<br>                           coll=&#39;input&#39;,<br>                           <strong>bucket_auto=True</strong>)</pre><h4>Doing a Transform with the Data</h4><p>In python, you can use Apache Beam SDK for Python and its key concepts to do a basic transform. Check out the Ptransformmodule <a href="https://beam.apache.org/releases/pydoc/2.27.0/apache_beam.transforms.ptransform.html"><em>here</em></a><em>.</em></p><p>PCollectionrepresents a collection of data.</p><p><a href="https://beam.apache.org/releases/pydoc/2.27.0/apache_beam.transforms.ptransform.html#apache_beam.transforms.ptransform.PTransform">PTransform</a> represents a computation that transforms PCollections. You can <strong>chain</strong> transforms together to create a pipeline that successively modifies input data.</p><h4>Simple Transforms</h4><p>Usually, for simple transforms, use a ParDo transform. Check out core beam transforms <a href="https://beam.apache.org/documentation/programming-guide/#core-beam-transforms"><em>here</em></a><em>.</em></p><p>Pardoconsiders each element in the input PCollection, performs actions and emits zero, one, or multiple elements to an output PCollection.</p><p>Example usage:</p><pre><strong># </strong><strong>The DoFn to perform on each element in the input PCollection<br>class</strong> <strong>ComputeWordLengthFn</strong>(beam<strong>.</strong>DoFn):<br>  <strong>def</strong> <strong>process</strong>(self, element):<br>    <strong>return</strong> [len(element)]</pre><h4>Composite Transforms</h4><p>Sometimes you need to do multiple simpler transforms (such as more than one ParDo, Combine, GroupByKey) when applying a transform to input data. These transforms are called composite transforms. In this case, you need to use Ptransform module. Here is an example of usage from the docs.</p><pre><em># The CountWords Composite Transform inside the WordCount pipeline.</em><br><strong>class</strong> <strong>CountWords</strong>(beam<strong>.</strong>PTransform):<br>  <strong>def</strong> <strong>expand</strong>(self, pcoll):<br>    <strong>return</strong> (<br>        pcoll<br>        <em># Convert lines of text into individual words.</em><br>        <strong>|</strong> &#39;ExtractWords&#39; <strong>&gt;&gt;</strong> <strong>beam.ParDo</strong>(ExtractWordsFn())<br>        <em># Count the number of times each word occurs.</em><br>        <strong>|</strong> <strong>beam.combiners.Count.PerElement()</strong><br>        <em># Format each word and count into a printable string.</em><br>        <strong>|</strong> &#39;FormatCounts&#39; <strong>&gt;&gt;</strong> <strong>beam.ParDo</strong>(FormatCountsFn()))</pre><p>A PTransform derived class needs to define the expand() method that describes how one or more PValuesare created by the transform.</p><p>Now, since you know how to read data, apply a transform and write the output; you can create a pipeline.</p><p>Let’s say you want to read the data from the database, trim a field and write to another collection or the same collection using Apache Beam.</p><p>In the case of a Trim transform, here is how you can achieve a simple transformation with beam.DoFn class.</p><pre><strong>class </strong>TrimTransform(beam.DoFn):<br>  <strong>def</strong> <strong>process</strong>(self, element):<br>      element = element.strip()<br>      <strong>yield </strong>element</pre><p>Inside your <strong>DoFn </strong>subclass, you define a <strong>process </strong>method where you provide the actual transform logic. The Beam SDKs handle extracting the elements from the input collection so you get the <strong>extracted element as a parameter.</strong></p><p><strong>Note: </strong>Once you output a value using <strong>yield </strong>or <strong>return</strong>, you should not modify that value in any way.</p><p>Example of Trim class which contained the pipeline:</p><pre><strong>class Trim():</strong><br><strong>  def run(self):</strong><br>  database = self.database<br>  collection = self.collection<br>  output_collection = self.output_collection<br>  field = self.operation[&#39;field&#39;] <strong># In my case this is the field I am going to trim<br>  </strong></pre><pre><strong> # Define the transform class you will use in the pipeline<br> class TrimTransform(beam.DoFn):<br>    def process(self, element):</strong><br>      if field in element:<br>        element[field] = element[field].strip()<br>        <strong>yield </strong>element</pre><pre><strong># Define pipeline options</strong><br>options  = PipelineOptions()<br>options.view_as(StandardOptions).streaming = False</pre><pre><strong># Create pipeline</strong><br>pipeline = beam.Pipeline(options=options)</pre><pre>(<br>  pipeline | &#39;Read data&#39; &gt;&gt;          <strong>beam.io.ReadFromMongoDB</strong>(uri=&#39;mongodb://127.0.0.1&#39;,    db=database,coll=collection)</pre><pre>| &#39;Apply Transform&#39; &gt;&gt; <strong>beam.ParDo</strong>(TrimTransform())</pre><pre>| &#39;Save data&#39; &gt;&gt; <strong>beam.io.WriteToMongoDB</strong>(uri=&#39;mongodb://127.0.0.1&#39;, db=database, coll=output_collection)</pre><pre>)</pre><pre>result = pipeline.run()</pre><h4>Conclusion</h4><p>For simple transformations like trim or filter, you can use Mongodb aggregations. However, for complex transformations, using Apache Beam is a better choice. The Apache Beam SDK for Python provides access to Apache Beam classes and modules from the Python programming language. That’s why you can easily create pipelines, read from, or write to external sources with Apache Beam. Of course, there are a lot more capabilities you can do Apache Beam. For the next steps, you can explore windowing; grouping multiple elements, data encoding, type safety that Apache Beam provides out of the box.</p><p>Hope you enjoyed it!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=59e206a3802d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[42 Yazılım Okulu]]></title>
            <link>https://bilgedemirkaya.medium.com/42-yaz%C4%B1l%C4%B1m-okulu-b63dee778075?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/b63dee778075</guid>
            <category><![CDATA[yazılım]]></category>
            <category><![CDATA[42-silicon-valley]]></category>
            <category><![CDATA[yazılım-mühendisliği]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Sat, 03 Apr 2021 15:32:50 GMT</pubDate>
            <atom:updated>2021-04-04T11:55:15.616Z</atom:updated>
            <content:encoded><![CDATA[<p>2019&#39;dan beri öğrencisi olduğum 42 ile ilgili çok soru alıyorum. Yakin zamanda, Türkiye’de de 42 okulu açılacağını öğrendim. Merak edenler için biraz okulu anlatmak istiyorum.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QVSzcMCyCRSS5uMjg7bNpg.png" /></figure><p>Öncelikle 42 Paris, Fransada bir kaç milyarderin, kar amacı gütmeden tamamen ücretsiz olarak kurduğu bir okuldur. İlk başta Fransadaki iyi yazilimci açığını doldurmak için ortaya çıkmıştır. Daha sonra finansal desteklerle bir çok ülkede 42 Yazılım okulu açılmıştır ve aslında yeni bir okul tipine de öncülük etmektedir. Çünkü 42 tamamen ücretsizdir, Silicon Valley kampüsü gibi bir çok kampüsünde ayrıca yurtlar da ücretsizdir. (Amerika için devrimsel bir durum diyebilirim.) 42nin çok popülerleşmesi ile beraber, müfredatı ve eğitim şekli ile aynı tarzda Hive, 24 gibi bir çok yazılım okulu da değişik ülkelerde açılmıştır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J5NbHZGc2iNqQzZyNePHFg.jpeg" /><figcaption>Genellikle sayisiz Macbook dolu cool bir calisma ortamlari var</figcaption></figure><p>Ben kişisel olarak 42yi çok sevmeme rağmen, bu okulun herkes için olmayabileceğinin kanısındayım. Eğer okula başvurmayı düşünüyorsanız, bu kısımları kendiniz için iyi değerlendirmeniz gerektiğini düşünüyorum.</p><p>42 sadece yazılım mühendisliği eğitimi verir. Hiç bir kadrolu öğretmeni yoktur. 42 aslında size nasıl öğreneceğinizi öğretmeyi hedefler ve gerisini size bırakır. Okul müfredatı içinde, bilgilendirici video kayıtlı dersler ve çok sayıda seminer olmasına rağmen, herhangi bir ders verilmez. Okula başvurmak için, yapılan ufak bir online test dışında herhangi bir ön koşul aranmaz, daha öncesinde yazılım bilmeniz beklenmez. Test ise gayet basit bir yazılım direktifi oyunudur ve istediğiniz kadar tekrarlayabilirsiniz. Başvurduktan sonra 1 aylık bir seçim sürecini başarı ile tamamlarsanız okula kabul edilmiş olursunuz.</p><p>Level 0 ile okula başlarsınız, müfredat boyunca bitirdiğiniz yazılım projeleriyle ve geçtiğiniz sınavlarla beraber level seviyeniz artar. Aslında normal üniversite eğitiminde 2 level 1 öğretim yılına denk gelmekte. 42 Pariste level 8e ulaşıldıgında lisans, level 10a ulaşıldığında master derecesi alırsınız. Ancak benim bildiğim kadarıyla, Fransa dışındaki 42 okulları devlet tarafından resmi olarak akredite olmadığı için resmi bir diploma verilmez. Özellikle Türkiyede diplomaya farklı bir anlam yüklendiği için bu durum herkese uygun gelmeyebilir.</p><p>Okul uzaktan eğitim imkanı sağlamaz ve yine ülkeye bağlı olmakla beraber okul labaratuvarında geçirmenız gereken belirli bir devam mecburiyeti var. Eğer belirli bir gün sayısı boyunca hiç proje bitirmezseniz (buna black hole diyoruz ) okulla ilişiğiniz kesilmiş olur.</p><p>Okulun resimdeki gibi bir müfredat çizgisi var, grup ya da bireysel projeler ve sınavları bitirdikçe genişleyerek açılan projeleri takip etmeniz gerekmekte.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/838/1*LAVHkgE2mYEaFzPmGCSl2A.png" /></figure><p>Bir çok kampüste belirli bir levele ulaşana kadar sadece C yazılım dili kullanılır. Ve bir çok C fonksiyonu kullanmak da yasaktır. Projeleri özellikle zor yapan kısım da bu fonksiyonları en bastan sizin yazmanızı beklemeleridir. 42nin en çok eleştirildiği noktalardan birisi de sadece C dili kullanılması. Bunun da sebebi güncel kullanılan teknolojilerden uzak olması ve sadece C dilinin genellikle bir iş için yeterli olmaması. Ancak 42 sizi işe hazırlayan bir bootcamp değildir. Tam tersi yaklaşık 3 yıl süren yoğun bir yazılım mühendisliği eğitimidir. Size kendi kendinize öğrenmeyi ve sağlam bir muhendislik temeli vermeyi hedefler.</p><p>Belli bir levele geldikten sonra ise öğrenci hangi alanda yoğunlaşmak istediğini seçip o kısımın projeleri ile devam eder (Son halka). Alacagınız projeler seçtiğiniz alana ve yazılım diline göre değişir. Bunun haricinde bütün projeler için norminette adı verilen style pattern vardır ve bunu takip etmeden yazılmış hiç bir proje değerlendirmeye alınmaz.</p><p>Bir proje tamamlandığı zaman, evaluation dediğimiz bir süreç başlar. Bir projenin 3 ayrı 42 öğrencisi tarafından 2 gün içinde onaylanması gerekir. Yani öğrenci, 3 ayrı defa -kimden alacagini bilmeden- değerlendirme randevusu alır. Yaklaşık 30dk sürer, projeyi ve orada neyi neden kullandığını anlatır. Evaluation yapan kişi kod için test yazmaktan ve öğrencinin kopya çekip çekmediğini, projeyi anlayarak yapıp yapmadığını kontrol etmekten sorumludur. Eğer 3 kişiden 1si projeyi onaylamazsa, öğrenci projeden kalır. 3ü de onaylarsa, bir kez de sistem ( Moulinette) yazılan kodu test eder. Moulinette de onayladığı takdirde proje başarı ile tamamlanmış olur.</p><p>Evaluation yapan öğrenci 1 eval puanı kazanmakta, yaptıran öğrenci ise 1 tane kaybetmektedir. Yani sürecin devamı için her öğrenci aynı zamanda başkalarını kontrol etmelidir. Bu durum öğrencilerin code review becerilerini geliştirir, iyi ve kötü kodu birbirinden ayırmak için bu çok önemlidir. Aynı zamanda diğer öğrenciye kodunu savunmayı öğretir. Kodu kontrol eden kişi de aşağı yukarı sizinle aynı seviyede olacagı için, size yanlış bir öneride bulunsa bile, siz ona ‘ ben bunu bu şekilde şuradan öğrendim, bu bu sebepten dolayı da verdiğin bu öneri yanlış’ diyebilmelisiniz. Takıldıgınız zamanlar ise bocal dediğimiz, 42 gorevlilerine danışabilirsiniz. Bu ‘peer to peer’ dedigimiz öğrenme şekli herkese uygun olmayabilir. Başka bir platformda aynı seviyede olduğum bir kişiye öneri verdiğim için eleştirilmiştim örneğin. Eğer yanlış düşünüyorsam, onu da yanlış yönlendirebilirim sebebi ile. Ancak 42 kültüründe bu durumun tam tersi geçerlidir.</p><p>Okulun en sevdiğim özelliklerinden birisi de, zor ve yoğun bir müfredatı olmasına karşın, özgürce hareket edebilmenize olanak sağlaması. Bir projeyi istediğiniz zamanda tamamlayabilirsiniz, eğer kısa sürede üst üste 2–3 proje tamamlarsanız, aylarca kendi işinize de bakabilirsiniz örneğin. Çünkü bir proje tamamladığında, black hole dediğimiz gün sayısına belli sayıda gün eklenir. Örnek vermek gerekirse, okula ilk başladığımda 50 günüm vardı black hole’a girmemek için. İlk projemi tamamladığımda 30 gün eklenerek 80&#39;e çıkmıştı. Bunun dışında toplamda 180 günlük olmak üzere, 3 kere okulu dondurma hakkınız var.</p><p>Sınavlar kesinlikle kampüs labaratuvarında gerçekleşir. Sınavda belirli bir sürede, rastgele gelen soruları cevaplamanız beklenmektedir. Genellikle projelerdekine benzer, daha kısa sürede cevaplayabileceğiniz sorular sorulur. C dilinde leetcode, codewars soruları gibi de düşünebilirsiniz. Sınav sırasında ayrıca kendiniz kodu test etmelisiniz. Kaldığınız zaman istediğiniz kadar tekrarlayabilirsiniz. Tek zorunluluk black hole süreniz dolmadan tamamlamış olmanız.</p><p>1i startupta olmak üzere 2 zorunlu stajı vardır. Fransa kampüsünde level 8den sonra sizi şirketlerle birebir görüştüren ve staj ya da iş bulmanıza yardımcı olacak bir sistemleri var. Ancak okuldan okula değişiyor diye biliyorum.</p><p>Transferlerle ilgili çok bilgim olmadığı için bu konuda kesin bir şey söyleyemiyorum. Ancak bildiğim kadarıyla Level 10dan sonra herhangi bir ülkedeki herhangi bir 42 okuluna transferinizi isteyebiliyorsunuz. Ben Covid-19 dolayısıyla 42 Silicon Valley kampüsünden Paris kampüsüne kolaylıkla transfer oldum.</p><p>Okulun 42 networku çok gelişmiş bir yapıda, bir çok konuda ( örneğin kendi startupınızı kurmak istiyorsanız, ya da bir 42 startupında iş deneyimi edinmek istiyorsanız) çok gelişmiş bir öğrenci ve mezun ağları var. Sürekli önemli kurum ve kişilerle etkinlik düzenleyerek yeni fırsatlara kolayca erişmenizi sağlıyorlar. Bütün 42 kampusleri ve sadece kampüse özel olmak üzere bir çok slack kanalından herkese kolayca ulaşabiliyorsunuz.</p><p>Son olarak, okul özellikle Fransada çok saygın bir konumda ve 42 öğrencileri genellikle unıcorn dediğimiz startup şirketlerde çalışma imkanı buluyor. Bir çok arkadaşım şimdiden Apple, Facebook gibi şirketlerde çalışıyor. Bu yüzden okula talep de git gide artmakta. Ben kişisel olarak, öğrenime çok faydalı olduğunu düşünüyorum ve eğer yazdığım kısımlar sizi rahatsız etmediyse en azından okul size göre mi diye test etmenizi tavsiye ederim. Zaten 1 aylık giriş sürecinde okulun yapısının size uyup uymadığını anlayabilirsiniz. Eğer kendi kendine öğrenmek size zor geliyorsa ve özellikle bir öğretmen direktifine ihtiyaç duyuyorsanız çok da memnun kalmayabilirsiniz. Bu okula kabul sürecinin ilk haftasında grubun yarısı okulu bırakmıştı örneğin. Okula giriş süreci ise apayrı bir konu olduğundan başka bir yazımda bahsetmeyi düşünüyorum. Eğer sorunuz varsa yorumda bahsederseniz, bir sonraki yazımda yanıtlamaya da çalışırım.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b63dee778075" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Make a Robust Crawler with Scrapy and Django]]></title>
            <link>https://codeburst.io/make-a-robust-crawler-with-scrapy-and-django-20e1bc199bca?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/20e1bc199bca</guid>
            <category><![CDATA[scrapy]]></category>
            <category><![CDATA[web-scraping]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[django]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Tue, 23 Mar 2021 15:15:07 GMT</pubDate>
            <atom:updated>2021-05-23T20:25:07.075Z</atom:updated>
            <content:encoded><![CDATA[<p>As a developer, you may find yourself wishing to gather, organize, and clean data. You need a scraper to extract data and a crawler to automatically search for pages to scrape.</p><p>Scrapy helps you complete both easy and complex data extractions. It has a built-in mechanism to create a robust crawler.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HaIhB4z43E4xYZH5" /></figure><p>In this article, we’ll learn more about crawling and the Scrapy tool, then integrate Scrapy with Django to scrape and export product details from a retail website. To follow this tutorial, you should have basic Python and Django knowledge and have Django installed and operating.</p><h3>Selectors</h3><p>Scraping basically makes a GET request to web pages and parses the HTML responses. Scrapy has its own mechanisms for parsing data, called selectors. They “select” certain parts of the HTML using either CSS or XPath expressions.</p><p><strong>Important note</strong>: Before you try to scrape any website, go through its robots.txt file. You can access it via<a href="http://www.google.com/robots.txt"> </a><em>&lt;domainname&gt;/robots.txt</em>. There, you will see a list of pages allowed and disallowed for scraping. You should not violate any terms of service of any website you scrape.</p><h3>XPath Expressions</h3><p>As a Scrapy developer, you need to know how to use XPath expressions. Using XPath, you can perform actions like select the link that contains the text “Next Page”:</p><pre>data = response.xpath<strong>(</strong>“//a[contains(., ‘Next Page’)]”<strong>)</strong>.get()</pre><p>In fact, Scrapy converts CSS selectors to XPath under the hood.</p><pre># sample of css expression<br>data = response.css(‘.price::text’).getall()</pre><pre># sample of a xpath expression<br>data = response.xpath(‘//h1[@class=”gl-heading”]/span/text()’).get()</pre><p>Expression // selects all elements that fulfil the criteria. If you specify an attribute with @ , it only selects elements with that attribute. /shows the path of the target element. After all, you need the full path of your target element. get() always returns a single result (the first one if there are many results). getall()returns a list with all results.</p><p>Note: You may have seen extract and extract_first instead of getall()and get()as they are the same methods. However, the official document indicates that these new methods result in a more concise and readable code.</p><h4>Starting a Scrapy Project</h4><p>After you install Scrapy, scrapy startproject &lt;projectname&gt; creates a new project.</p><p>Inside the project, type scrapy genspider &lt;spiderName&gt; &lt;domainName&gt; to set up the spider template.</p><p>To run the spider and save data as a JSON file, run scrapy crawl &lt;spiderName&gt; -o data.json.</p><h4>Integrating with Django</h4><p>scrapy-djangoitem package is a convenient way to integrate Scrapy projects with Django models. Install with pip install scrapy-djangoitem</p><p>To use the Django models outside of your Django app you need to set up the DJANGO_SETTINGS_MODULEenvironment variable. And modify PYTHONPATH to import the settings module.</p><p>You can simply add this to your scrapy settings file:</p><pre><strong>import sys</strong><br>sys.path.append(&#39;&lt;path-to-project&gt;/djangoProjectName&#39;)</pre><pre><strong>import os</strong><br>os.environ[&#39;DJANGO_SETTINGS_MODULE&#39;] = &#39;djangoProjectName.settings&#39;</pre><pre># If you you use django outside of manage.py context, you <br># need to explicitly setup the django<br><strong>import django</strong><br>django.setup()</pre><p>After integration, you can start working on writing your first spiders.</p><h4>Spiders</h4><p>Spiders are classes defining the custom behaviour for crawling and parsing a particular page. Five different spiders are bundled with Scrapy and you can write your own spider classes as well.</p><h4>Scrapy.spider</h4><p>Scrapy.spider is the simplest root spider that every other spider inherits from.</p><pre><strong>class MySpider(scrapy.Spider):<br></strong>name = ‘example’<br>allowed_domains = [‘example.com’]</pre><pre>start_urls = [<br>‘http://www.example.com/1.html&#39;,<br>‘http://www.example.com/2.html&#39;<br>]</pre><pre><strong>def parse</strong>(self, response):<br># xpath/css expressions here</pre><pre><strong>yield</strong>(item)</pre><p>Each spider must have:</p><ul><li><strong>name </strong>— should be unique.</li><li><strong>allowed_domains </strong>— specifies what domain it is allowed to scrape.</li><li><strong>start_urls</strong> — specify what pages you want to scrape within that domain.</li><li><strong>parse method</strong> — takes the HTTP response and parses the target elements that we specified with selectors.</li><li><strong>yield — </strong>keyword to generate many dictionaries containing the data.</li></ul><p>To set these properties dynamically, use __init__method. So you may use the data coming from your Django views:</p><pre><strong>class</strong> <strong>MySpider</strong>(scrapy.Spider):<br>    name = &#39;example&#39;</pre><pre><strong>def</strong> <strong>__init__</strong>(self, *args, **kwargs):<br>        self.url = kwargs.get(&#39;url&#39;)<br>        self.domain = kwargs.get(&#39;domain&#39;)<br>        self.start_urls = [self.url]<br>        self.allowed_domains = [self.domain]<br><strong>def</strong> <strong>parse</strong>(self, response):<br> ...</pre><p>You don’t need an additional method to generate your requests here, but how are the requests generated?<em> </em><em>Scrapy.spider</em> provides a default start_requests() implementation. It sends requests to the URLs defined in start_urls. Then it calls parse method for each response <em>one by one</em>. However, you may need to override it in some circumstances. For instance, if the page requires a login, you must override it with a POST request.</p><p>The other spiders Scrapy provides are <strong>CrawlSpider</strong>, which provides a convenient mechanism for the following links by defining a set of rules, <strong>XMLFeedSpider</strong> to scrape XML pages, <strong>CSVFeedSpider</strong> to scrape CSV files, and <strong>SitemapSpider</strong> to scrape URLs held in the sitemap file.</p><p><strong>Note: </strong>Scrapy is asynchronous<strong> </strong>by default which means you can <strong>chain </strong>your responses. So requests are scheduled and processed (one by one) <strong>asynchronously.</strong></p><pre><strong>def parse(self, response)</strong>:</pre><pre><strong>for page in range(self.total_pages):</strong> <br> url = &#39;https://example.com/something.html&#39;<br>    for page in range(self.total_pages): <strong># </strong> <strong>each page is self explainable because it waits until previous page is done</strong><br>     <strong>yield</strong> Requests(url.format(page), callback=self.parse)</pre><h4>Items</h4><p>Spiders can return the extracted data as Python key-value pairs. This is similar to Django models except that it is much simpler. You can choose from different item types like dictionaries or item objects. You can also adjust different types using itemadapter</p><pre>#items.py</pre><pre><strong>class</strong> <strong>BrandsItem</strong>(scrapy.Item):<br>    name = scrapy.Field()<br>    price = scrapy.Field() <br>    ..</pre><p>You may use scrapy-djangoitem extension that defines Scrapy Items using existing Django models.</p><pre>from <strong>scrapy_djangoitem</strong> import <strong>DjangoItem</strong><br>from <strong>products.models</strong> import <strong>Product</strong></pre><pre><strong>class BrandsItem(DjangoItem): </strong><br>   <strong>django_model = Product</strong><br>   stock = scrapy.Field() <strong># You can still add extra fields</strong></pre><p>When you declare an item class, you can directly save data as items.</p><pre># Inside spider class<br>...</pre><pre><strong>def parse(self, response): <br>  item </strong>= <strong>BrandsItem()</strong><br>  <strong>item[&#39;brand&#39;]</strong> = &#39;ExampleBrand&#39;<br>  <strong>item[&#39;name&#39;]</strong>= response.xpath(&#39;//h1[@class=”title”]/text()&#39;).get()<br>  ..<br>  <strong>yield(item)</strong></pre><h4>Item Pipeline</h4><p>The Item Pipeline class basically receives and processes an item. It may validate, filter, drop and save items to the database. To use it, you should enable it in the settings.py.</p><pre>ITEM_PIPELINES = { ‘amazon.pipelines.AmazonPipeline’: 300}</pre><p>Each item pipeline has a process_itemmethod that returns the modified item or raises a dropItem exception.</p><pre># useful for handling different item types with a single interface<br>from itemadapter import ItemAdapter</pre><pre><strong>class BrandsPipeline:</strong></pre><pre># parameters are scraped item and its spider<strong><br>def</strong> <strong>process_item(self, item, spider)</strong>: <br>        adapter = ItemAdapter(item)<br>        <strong>if</strong> adapter.get(&#39;price&#39;): <strong># if scraped data has a price</strong><br>           item.save()<strong> # save it to database</strong> <br>           <strong>return</strong> item<br>        <strong>else</strong>:<br>            <strong>raise</strong> DropItem(f&quot;Missing price in <em>{</em>item<em>}</em>&quot;)</pre><h4>Run Spiders with Django Views</h4><p>Instead of the typical way of running Scrapy, via scrapy crawl, you can connect your spiders with django-views, which automates the scraping process. This creates a real-time full-stack application with a standalone crawler.</p><p>The whole process is described in the image below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*26rEcLHEhdXBwZE2" /></figure><p>The client sends a request to the server with URLs to scrape. URLs might come with user input or something else depending on your needs. The server takes the request, triggers Scrapy to crawl the target elements. Spiders use selectors to extract data. It might use Item Pipeline to customize it before storing it. Once data is in storage, it means scrapy status is finished. As the last step, your server may call back that data from the storage and send it with a response to the client.</p><p>The problem in this process is in the seventh step. There is no way for the Django app to know when the scaping status is finished. So, to have a persistent connection with your server, you may need to send requests to it every second, asking, “Hey! Is there anything else?” However, it is not an effective way to build a real-time application. A better solution is to use web sockets. The Django channels library establishes a WebSocket connection with the browser.</p><p>Helper libraries can help creating your real-time application with Scrapy. Scrapyd is a standalone service running on a server where you can deploy and control your spiders. The ScrapyRT library ensures responses are returned immediately as JSON instead of having the data saved in a database, so you can create your own API.</p><h4>Next Steps</h4><p>This article is intended to be a practical guide to those who want to explore Scrapy structure beyond connecting it with Django. There are a lot more things you can do with Scrapy. With a couple of lines, you can design a web crawler that automatically navigates to your target website and extracts the data you need. Many websites run entirely on JavaScript nowadays. So sometimes you may need to open a modal or press a button to scrape data. This would become a nightmare if you use other tools instead of Scrapy. Thankfully, there is a plugin for scrapy-splash integration for handling JavaScript code easily for your target website. Besides, Scrapy handles errors gracefully. It even has a built-in ability to resume scraping from the last page if it encounters an error from the page. Although you get all of them for free, you need to allocate some time to learn it as it is not as easy to use compared to other scraping tools. For the next steps, if you are intended to create your standalone crawler, you may find <a href="https://github.com/adriancast/Scrapyd-Django-Template">adriancast’s</a> Scrapyd-Django-Template helpful. Check out how they implemented Scrapyd to deploy and run Scrapy spiders inside the Django app.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=20e1bc199bca" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/make-a-robust-crawler-with-scrapy-and-django-20e1bc199bca">Make a Robust Crawler with Scrapy and Django</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[An Introduction to Web Scraping]]></title>
            <link>https://codeburst.io/an-introduction-to-web-scraping-820755f36e1d?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/820755f36e1d</guid>
            <category><![CDATA[web-crawling]]></category>
            <category><![CDATA[scrapy]]></category>
            <category><![CDATA[beautifulsoup]]></category>
            <category><![CDATA[web-scraping]]></category>
            <category><![CDATA[faq]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Mon, 22 Feb 2021 16:51:54 GMT</pubDate>
            <atom:updated>2021-02-22T16:52:08.685Z</atom:updated>
            <content:encoded><![CDATA[<p><em>If the only way you access the Internet is through your browser, you are missing out on a huge range of possibilities.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-uOd4uP3LIABwGdTtolFkA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@nate_dumlao?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Nathan Dumlao</a> on <a href="https://unsplash.com/s/photos/spider-web?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>If you search “<em>Cheapest Flight to Istanbul</em>” on Google, you will get some popular flight search website results as well as some advertisements. Google will only report what these websites say in their content. On the other hand, however, a well-prepared scraper can provide far greater information including a detailed chart of <em>flights to Istanbul</em> containing price changes over time, as well as a suggestion for the best time to buy the tickets to Istanbul by gathering data across a variety of websites.</p><h3>So, what is Web Scraping exactly?</h3><p>In general terms, the main goal of web scraping is to extract structured data from the unstructured web pages. <strong>Web scraping</strong>, <strong>web harvesting</strong>, or <strong>web data extraction</strong> is <a href="https://en.wikipedia.org/wiki/Data_scraping">data scraping</a> used for <a href="https://en.wikipedia.org/wiki/Data_extraction">extracting data</a> from websites.</p><p>There are different techniques and powerful tools you can do web scraping. For example, if you manually <strong>copy-paste the data from a web page to a text editor</strong>, you are carrying out a basic form of web scraping. In fact, this technique might be the best method to employ when websites explicitly set up barriers to prevent machine automation.</p><h3>Should I use API instead of scraping?</h3><p>APIs can be extremely useful if you find the ones that satisfy your needs. However, it’s more likely that the API you’d like to use may not exist or that it may not be useful for your purposes.</p><ol><li>If you need to collect data from a various number of websites, you will probably struggle to find each of the APIs. Perhaps some websites might not want to share their data or might not prepare an API even.</li><li>Sometimes when you find a useful API, they may limit requests coming from the same IP. They would also limit data to share with their APIs.</li></ol><p>As a result, when you need to gather data across websites and the given API is not useful for your purposes (due to the reasons above), web scraping is going to your best option.</p><h3>How to know when and when not to scrape.</h3><p>I was astonished to learn that, with few exceptions, if you can view data in your browser then you can access it via a script. This is because if you access data via a script, you can store it in your database and do anything with the data from there.</p><h3>But is it legal?</h3><p>This is a question that I really struggled to find an answer to. I even reached out to some big companies and asked ‘<strong>is it okay to scrape you?</strong>’ If you email as I did, many companies will never tell you that you can scrape them. In fact, big companies use scraping themselves but also don’t want others to use bots against them. In case you hadn’t realized it yet; <strong>Google search</strong> is both a <strong>web crawler</strong> and a <strong>web scraper</strong>. Google’s crawler is known as <strong>Googlebot</strong>. <a href="https://youtu.be/BNHR6IQJGZs">Through crawling and scraping of data, Googlebot discovers</a> new and updated pages to add to the Google search index.</p><p>Recently, music lyrics repository Genius accused Google of lifting lyrics and posting them on its search platform. However, the court has dismissed this lawsuit.</p><p><a href="https://techcrunch.com/2020/08/11/court-dismisses-genius-lawsuit-over-lyrics-scraping-by-google/">Court dismisses Genius lawsuit over lyrics-scraping by Google</a></p><p>While data gathering is <strong>legal </strong>in many countries, it <strong>varies across the world</strong> and has some<strong> ambiguity from country to country.</strong> With this in mind, here are some good rules to follow:</p><ul><li>Be careful not to cause damage or use data for bad purposes. There are lots of bad bots out there and many of them eventually get sued.</li><li>It is most certainly <strong>illegal </strong>to <strong>analyze, change, manipulate data or sell it to someone else.</strong></li></ul><p>I found this article useful for more details:</p><p><a href="https://medium.com/datadriveninvestor/web-scraping-for-data-science-is-it-legal-266fb51171ec">Web Scraping for Data Science — Is it legal?</a></p><p>Most say that as long as you’re scraping public information, and not causing any damage to anybody while doing so, your actions are<strong> legal</strong>.</p><p><strong>Fun fact:</strong> Amazon is the most scraped website in the world.</p><h3>What about the security checks of the websites?</h3><p>I advise you to respect their security checks and scraping protection mechanisms. You can check them at ‘<strong><em>domainname/robots.txt’. </em></strong>You can get banned from scraping them after frequent attempts. However, know that most of them are surmountable. A sample solution to IP ban:</p><p><a href="https://stackoverflow.com/questions/35133200/scraping-in-python-preventing-ip-ban/35133929#35133929">Scraping in Python - Preventing IP ban</a></p><h3><strong>What is the best language and tools and for web scraping?</strong></h3><p><strong>Python</strong> is the most popular language for web scraping. It can handle almost all of the data extraction processes and most of the web scraping requirements.</p><p><strong>Scrapy, Selenium and Beautiful Soup </strong>are the most widely used web scraping frameworks written in Python.</p><p><strong>Scrapy </strong>builds a robust system for extracting data even from complicated websites with lots of security checks. It’s 20 times faster than other tools. If your project is a big one and needs proxies, data pipeline, I recommend Scrapy even though it might take a little time to master it.</p><p>Check this link out for more detail:</p><p><a href="https://medium.com/analytics-vidhya/scrapy-vs-selenium-vs-beautiful-soup-for-web-scraping-24008b6c87b8">Scrapy Vs Selenium Vs Beautiful Soup for Web Scraping.</a></p><h3>Is web scraping different from web crawling?</h3><p>Yes. When you only need data from a specific URL, use a <strong>web scraper</strong>. When you need to get URLs to scrape first and then get the data off them, use both a <strong>web crawler</strong> and a <strong>web scraper</strong>. While the web crawler creates the URLs to fetch, the web scraper will take the data out of those pages.</p><p>Let’s say you want to search for a whole website with a t-shirt keyword and then get all of the t-shirt titles and prices.</p><p><strong>Step 1</strong>: Crawl the search URL, fetching all of the URLs with the t-shirt keyword.</p><p><strong>Step 2</strong>: Scrape each of the URLs of the list from step 1, and return the title and price of the t-shirts.</p><h3>Conclusion</h3><p>These are the questions that I struggled with when I am new to web scraping. I hope it will be a helpful tool to understand some basics of web scraping, thanks for reading!</p><p><strong>Please note:</strong> I am not an expert when it comes to the legality around the subject of web scraping and suggest that you do your own research regarding what is and isn’t legal when learning more about the subject. This article is intended to be a helpful introduction to the topic of web scraping and should not be used as legal advice for any of the topics covered here. Neither I nor Codeburst are responsible for any illegal action taken by readers in relation to web scraping or associated activities.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=820755f36e1d" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/an-introduction-to-web-scraping-820755f36e1d">An Introduction to Web Scraping</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Create A Popup Modal With CSS + JavaScript]]></title>
            <link>https://javascript.plainenglish.io/how-to-create-a-popup-modal-with-css-javascript-7e5d369ae6f?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/7e5d369ae6f</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-design]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[css]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Sun, 07 Feb 2021 17:53:39 GMT</pubDate>
            <atom:updated>2021-02-07T18:45:42.131Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5lLGYJXaxAKqdevef94-QQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@andrewtneel?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Andrew Neel</a> on <a href="https://unsplash.com/s/photos/europe-history?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>A modal is a popup window that is displayed in front of the current page when pressed a button.</p><p>Here’s my example, I have recently created a Twitter-like website using Django.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0uRh9suTo-Mk1PlzC1IRQA.jpeg" /></figure><h4>First step: style your parent section</h4><p>The first thing you want to do is create a semi-transparent black background. To do that you need to create a parent element which wraps your content section.</p><pre><em>&lt;div class=”bg-modal”&gt;<br> &lt;div class=”modal-content”&gt;<br> <br> &lt;/div&gt;<br> &lt;/div&gt;</em></pre><p>Let’s style this modal now:</p><pre>.bg-modal{<br> width:100%;<br> height:100%;<br> background-color: black;<br> }</pre><p>You also need to tell the background modal to lay over top of the content.</p><pre>position: absolute;</pre><p>When you say absolute, you need to say where it is.</p><pre>top:0px;</pre><p>The problem here is if we do <em>opacity: 0.7</em>for decreasing opacity of background,<em> </em>this opacity value will transfer to the child element no matter whether you specify the child element’s opacity or not. The solution is not to specify opacity in here but in the background colour.</p><pre>bacground-color: rgba(0,0,0,0.7) // the 4th number will be the opacity</pre><p><strong>Let’s look at what we have so far:</strong></p><pre>.bg-modal{<br> width: 100%;<br> height:100%;<br> background-color: rgba(0,0,0,0.5); /* make it half transparent */<br> position: absolute;<br> top:0px;<br> z-index: 1;<br> display: none;  /* It will remain invisible until you open */<br> justify-content: center; /*center horizontally*/ <br> align-items: center ; /* center vertically */}</pre><h4>Second Step: style your content section</h4><p>Here is mine.</p><pre>.modal-content{<br> width:600px;<br> height:300px;<br> background-color: white;<br> border:none; <br> border-radius: 15px;<br> padding:15px;<br> position: relative;<br> }</pre><p>If parent element’s position is <em>absolute</em> that means you choose the exact location for your elements. And you need to set your child element position <em>relative</em>. Consequently, when you specify the exact pixel location of the elements, it will position your child elements inside of parent element accordingly.</p><h4>Third Step: style the remove button</h4><p>Now you need a button that you can close your modal.</p><pre>&lt;div class=”close”&gt; + &lt;/div&gt;</pre><ul><li>I prefer to use + and rotate it in CSS code, which will give it a better look than using just X. However, it is up to you.</li></ul><p>This is how I style it:</p><pre>.close{<br> position: absolute;<br> top:5px;<br> right: 10px;<br> font-size:25px;<br> transform: rotate(45deg); /* will make it look like x */<br> cursor: pointer;<br> }</pre><p>Let’s add some JavaScript to make this button actually work. Right now our modal is hidden. All we want to do is click a button and open the popup.</p><pre>const openButton = document.getElementById(&#39;myBtn&#39;)<br>const modal =  document.querySelector(&#39;.bg-modal&#39;)</pre><pre>openButton.addEventListener(&#39;click&#39;, () =&gt; {<br>  modal.style.display =&#39;flex&#39;<br>}</pre><p>And click a button and hide the popup.</p><pre>const closeBtn =  document.querySelector(&#39;.close&#39;)<br>const modal =  document.querySelector(&#39;.bg-modal&#39;)</pre><pre>closeBtn.addEventListener(&#39;click&#39;, () =&gt; {<br>  modal.style.display =&#39;none&#39;<br>})</pre><h4>Conclusion</h4><p>It’s a simple JS, CSS code that will help you to moderate and style your website a lot. You can fill the content section as you wish. Hope this helps!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7e5d369ae6f" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/how-to-create-a-popup-modal-with-css-javascript-7e5d369ae6f">How To Create A Popup Modal With CSS + JavaScript</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Find The Most Frequent Element In An Array In JavaScript]]></title>
            <link>https://javascript.plainenglish.io/how-to-find-the-most-frequent-element-in-an-array-in-javascript-c85119dc78d2?source=rss-4b73bb1d006d------2</link>
            <guid isPermaLink="false">https://medium.com/p/c85119dc78d2</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Bilge Demirkaya]]></dc:creator>
            <pubDate>Fri, 05 Feb 2021 16:28:32 GMT</pubDate>
            <atom:updated>2021-02-18T18:59:35.596Z</atom:updated>
            <content:encoded><![CDATA[<h3>Easiest Way to Find the Most Frequent Element in Array</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VStEGWJRRFZXIBXpe8ZmwQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@casparrubin?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Caspar Camille Rubin</a> on <a href="https://unsplash.com/s/photos/javascript?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>First of all, while browsing, I couldn’t find the most effective and short solution to find the most frequent element in an array but I only found a lot of long solutions with for loop however the best way is<strong> not using nested for loop.</strong> Because in Big O Notation, it’s a O(n2) complexity which means it is not effective.</p><p>The best way to find the most frequent element in an array is by using reduce function and creating a hashmap. And that’s the whole code you need:</p><pre>function getMostFrequent(arr) {<br>   const hashmap = arr.reduce( (acc, val) =&gt; {<br>    acc[val] = (acc[val] || 0 ) + 1<br>    return acc<br> },{})<br>return Object.keys(hashmap).reduce((a, b) =&gt; hashmap[a] &gt; hashmap[b] ? a : b)<br>}</pre><p>What I did was, creating a hashmap using reduce. If we have an array like [‘john’, ‘doe’, ’john’, ’bilge’], our hashmap will look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/279/1*cWmFdzad5JVm02XpMj4fXg.jpeg" /></figure><p>Because we create an object using acc in the first reduce function, notice <strong>the initial value of </strong><strong>acc is {}</strong>.</p><p>Then we check for each value of the array: is this value already in acc?</p><p>If no, put a key-value pair in the object. ( first appearance of the element)</p><p>If yes, increment the value of it.</p><p>Once we have the hashmap with elements and their occurrence number in the array, then we just need to get the key with the biggest value.</p><p>For that, we simply find the biggest value in the array and return the key of it with the reduce function like this.</p><pre>Object.keys(hashmap).reduce((a, b) =&gt; hashmap[a] &gt; hashmap[b] ? a : b)</pre><p><strong>Note: </strong>As you probably noticed, this will return <strong>only one key with the highest value</strong>, if you have two elements with the highest value and you want to return an array of it then you need to change the second reduce function.</p><p><strong>In case you have not only one maximum in the array and you want to return an array of max values you can use:</strong></p><pre>return Object.keys(hashmap).filter(x =&gt; {<br>             return hashmap[x] == Math.max.apply(null, <br>             Object.values(hashmap))<br>       })</pre><p>Notice this will return an array of the most frequent element, even if there is one. It will filter the elements which have not the max value and return it.</p><h4>Conclusion</h4><p>And there we have it! How to find the most common element in an array. I hope you have found this useful!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c85119dc78d2" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/how-to-find-the-most-frequent-element-in-an-array-in-javascript-c85119dc78d2">How To Find The Most Frequent Element In An Array In JavaScript</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>